home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume20 / log_tcp / part01 next >
Encoding:
Text File  |  1991-05-21  |  37.3 KB  |  1,063 lines

  1. Newsgroups: comp.sources.misc
  2. From: Wietse Venema <wietse@wzv.win.tue.nl>
  3. Subject:  v20i008:  log_tcp - Package to monitor and control TCP/IP connections, Part01/01
  4. Message-ID: <1991May22.041142.17009@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 8ca383a2e6437bbc374593e4378bf0f1
  6. Date: Wed, 22 May 1991 04:11:42 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Wietse Venema <wietse@wzv.win.tue.nl>
  10. Posting-number: Volume 20, Issue 8
  11. Archive-name: log_tcp/part01
  12. Supersedes: log_tcp: Volume 16, Issue 62
  13.  
  14. This package provides a couple of tiny programs that log all requests
  15. to connection-oriented tcp/ip services (examples: FINGER, SYSTAT, FTP,
  16. TELNET, RLOGIN, RSH, EXEC), with optional access control on the basis
  17. of host (or domain) names, internet addresses (or network numbers) and
  18. daemon process names.
  19.  
  20. The programs are nothing but small front ends. By default, they just
  21. log the remote host name and then invoke the real daemon. The programs
  22. should not require any changes to existing software or configuration
  23. files.
  24.  
  25. Enhancements over the previous release are: protection against rlogin
  26. and rsh attacks through compromised domain name servers, optional
  27. netgroup support for systems with NIS (formerly YP), and an extension
  28. of the wild card patterns supported by the access control files.
  29.  
  30.     Wietse Venema (wietse@wzv.win.tue.nl),
  31.     Eindhoven University of Technology,
  32.     The Netherlands.
  33. ---------
  34. #! /bin/sh
  35. # This is a shell archive.  Remove anything before this line, then unpack
  36. # it by saving it into a file and typing "sh file".  To overwrite existing
  37. # files, type "sh file -c".  You can also feed this as standard input via
  38. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  39. # will see the following message at the end:
  40. #        "End of shell archive."
  41. # Contents:  README miscd.c tcpd.c fromhost.c hosts_access.c Makefile
  42. #   hosts_access.5 strcasecmp.c BLURB
  43. # Wrapped by wietse@wzv on Mon May 20 13:35:39 1991
  44. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  45. if test -f README -a "${1}" != "-c" ; then 
  46.   echo shar: Will not over-write existing file \"README\"
  47. else
  48. echo shar: Extracting \"README\" \(8553 characters\)
  49. sed "s/^X//" >README <<'END_OF_README'
  50. X@(#) README 1.4 91/05/20 13:30:17
  51. X
  52. XGeneral description:
  53. X--------------------
  54. X
  55. XWith this package you can monitor connections to the SYSTAT, FINGER,
  56. XFTP, TELNET, RLOGIN, RSH and EXEC network services.  Connections are
  57. Xlogged through the syslog(3) facility. A requirement is that daemons
  58. Xare started by the inetd program or something similar.
  59. X
  60. XThe programs are tiny front ends that just report the remote host name
  61. Xand then invoke the real network daemon.  In the most common case, no
  62. Xchanges should be required to existing software or to configuration
  63. Xfiles.  Just move the vendor-provided daemons to another place and
  64. Xinstall the front ends into their original places. Installation details
  65. Xare given below.
  66. X
  67. XEarly versions of the programs were tested with Ultrix >= 2.2, with
  68. XSunOS >= 3.4 and ISC 2.2. The first official release has been installed
  69. Xon a wide variety of systems (BSD, SYSV, Apollo) without modification.
  70. XThe present release should still run on top of most BSD-style TCP/IP
  71. Ximplementations.
  72. X
  73. XOptional feature:
  74. X-----------------
  75. X
  76. XWhen compiled with -DHOSTS_ACCESS, the front-end programs support a
  77. Xsimple form of access control that is based on host (or domain) names,
  78. Xinternet addresses or network numbers, network daemon process names and
  79. X(optionally) netgroups (a NIS, formerly YP, feature).  Wild cards are
  80. Xsupported.  If a host requests connection to a network daemon, and if
  81. Xthe (daemon, host) pair is matched by an entry in the /etc/hosts.allow
  82. Xfile, access is granted.  Otherwise, if the (daemon, host) pair is
  83. Xmatched by an entry in the /etc/hosts.deny file, access is denied.
  84. XOtherwise, access is granted.  More details are provided in the
  85. Xhosts_access(5) manual page.  This form of access control may be useful
  86. Xif it can not be implemented at a more suitable level (such as an
  87. Xinternet router).
  88. X
  89. XMajor enhancement:
  90. X------------------
  91. X
  92. XIt has been brought to my attention that authentication based on host
  93. Xaddress to host name mapping can easily be spoofed by playing games
  94. Xwith some domain name server.  A little research led me to the conclusion
  95. Xthat many existing rshd and rlogind implementations do not account for
  96. Xthis potential problem.
  97. X
  98. XThe present versions of the front-end programs provide a way to take
  99. Xcare of the problem.  After mapping a client host address to a host
  100. Xname, the front-end programs now verify that the host name maps to the
  101. Xsame host address.  The idea is that it is much easier to compromise
  102. Xthe address->name map of some random name server than to compromise the
  103. Xname->address map that is specific to your domain.  If the source is
  104. Xcompiled with -DPARANOID, the front ends justs drop the connection in
  105. Xcase of a host name/address mismatch. Otherwise, the front ends just
  106. Xignore the bad host name and use the host address when consulting the
  107. Xaccess control files.
  108. X
  109. XMinor enhancements: 
  110. X-------------------
  111. X
  112. XThe host access control files now support more types of wild cards and
  113. X(optionally) allow the use of netgroup names.  Netgroup support is
  114. Xusually available on systems with NIS (formerly YP) software.
  115. X
  116. XRelated software:
  117. X-----------------
  118. X
  119. XVersions of rshd and rlogind, hacked to report the remote user name as
  120. Xwell, are available for anon ftp (ftp.win.tue.nl:/pub/logdaemon.tar.Z).  
  121. XThat archive also contains a tftpd source that logs the remote host
  122. Xname (nice if you want to know who is interested in your /etc/passwd
  123. Xfile).  All those programs have been tested only with SunOS >= 4.0.
  124. X
  125. XAnother way to manage access to tcp/ip services is illustrated by the
  126. Xservers provided with the authutil package (comp.sources.unix volume
  127. X22). This has the advantage that one will get the remote username from
  128. Xany host supporting RFC 931 security.  By installing the auth package
  129. X(same volume) one supports RFC 931 security too (but you will have to
  130. Xbelieve what the remote host tells you).  Eventually one can start
  131. Xcutting off unauthenticated connections. This is obviously a much more
  132. Xadvanced approach than what my front-end programs provide. The present
  133. Xpackage is more suitable for those who lack the resources to install
  134. Xanything that requires more than just renaming a couple of executables.
  135. X
  136. XConfiguration and installation (the easy way):
  137. X----------------------------------------------
  138. X
  139. XAn advanced installation recipe is given lateron. The "easy way" recipe
  140. Xrequires no changes to existing software or configuration files.
  141. X
  142. XIf you don't run Ultrix, you don't need the miscd front-end program.
  143. XThe Ultrix miscd daemon implements among others the SYSTAT service,
  144. Xwhich pipes the output from the WHO command to standard output.
  145. X
  146. XBy default, the front-end programs assume that the vendor-provided
  147. Xdaemons will be moved to the "/usr/etc/..." directory.  If you want
  148. Xsomething else, adjust the REAL_DAEMON and the REAL_DAEMON_DIR macros
  149. Xin the files miscd.c and tcpd.c.
  150. X
  151. XBy default, connections are logged to the same place where the sendmail
  152. Xlog entries go.  If connections should be logged elsewhere, adjust the
  153. XLOG_MAIL macro in the miscd.c and tcpd.c files, and update your syslog
  154. Xconfiguration file (usually, /etc/syslog.conf).  Most Ultrix versions 
  155. Xdo not provide this flexibility, though.
  156. X
  157. XBy default, the front-end programs support host access control.  Access
  158. Xcontrol is turned off when the /etc/hosts.{allow,deny} files do not
  159. Xexist. If you do not need support for host access control, adjust the
  160. Xmakefile so that the programs are compiled without -DHOSTS_ACCESS.
  161. XNote:  the host access control facility requires the strchr(), strspn()
  162. Xand strtok() routines.
  163. X
  164. XIf your C library does not provide the strcasecmp() routine, adjust the
  165. XAUX_OBJ macro in the Makefile so that it uses the strcasecmp() version
  166. Xprovided with this package.
  167. X
  168. XIn the Makefile, add -Dmemcmp=bcmp to the CFLAGS macro if your system
  169. Xdoes not have memcmp(), and add -DNETGROUP to the CFLAGS macro if your
  170. Xsystem supports netgroups.
  171. X
  172. XCompile with -DPARANOID if you want to drop connections when a remote
  173. Xhost name does not agree with the remote host address. This helps 
  174. Xagainst attacks through compromised domain name servers, but may
  175. Xoccasionally cause a perfectly legal connection to be refused due to
  176. Xtransient name server lookup problems.
  177. X
  178. XThe tcpd program is intended for monitoring connections to the telnet,
  179. Xfinger, ftp, exec, rsh and rlogin services. Decide which services you
  180. Xwant to be monitored. Move the vendor-provided daemon programs to the
  181. Xlocation specified by the REAL_DAEMON_DIR macro in the file tcpd.c, and
  182. Xcopy the tcpd front end to the locations where the vendor-provided
  183. Xdaemons used to be. That is, one copy of the tcpd front end for each
  184. Xservice that you want to monitor.
  185. X
  186. XUltrix only: if you want to monitor connections to the SYSTAT service,
  187. Xmove the vendor-provided miscd daemon to the location specified by the
  188. XREAL_DAEMON macro in the miscd.c file, and install the miscd front end
  189. Xinto the original miscd location.
  190. X
  191. XConfiguration and installation (the advanced way):
  192. X--------------------------------------------------
  193. X
  194. XInstead of moving the vendor-provided daemons to another directory,
  195. Xdefine the REAL_DAEMON_DIR to reflect the present location of those
  196. Xdaemons, and install the tcpd command in the same directory. Then do
  197. Xthe following edits to the inetd configuration file (usually in
  198. X/etc/inetd.conf):
  199. X
  200. X    telnet  stream  tcp     nowait  root    /usr/etc/in.telnetd     in.telnetd
  201. X
  202. Xbecomes:
  203. X
  204. X    telnet  stream  tcp     nowait  root    /usr/etc/tcpd           in.telnetd
  205. X
  206. X(the example applies to SunOS 4.x; other UNIX implementations should
  207. Xnot differ much). Similar changes will be needed for the other services
  208. Xthat are to be covered by the tcpd front-end program.
  209. X
  210. XApollo UNIX users will want to install the front end under a different
  211. Xname because tcpd is the name of an already existing command. A suitable 
  212. Xname for the front-end program would be "frontd".
  213. X
  214. XThe same trick can be played with the Ultrix miscd daemon but then the
  215. Xdaemon front end will have to be installed under a different name.
  216. X
  217. XAcknowledgements:
  218. X-----------------
  219. X
  220. XThanks to Brendan Kehoe (brendan@cs.widener.edu), Heimir Sverrisson
  221. X(heimir@hafro.is) and Dan Bernstein (brnstnd@kramden.acf.nyu.edu) for
  222. Xfeedback on an earlier release of this product.  Thanks to John Kimball
  223. X(jkimball@src.honeywell.com) for suggesting the host name to host
  224. Xaddress mapping check. Willem-Jan Withagen (wjw@eb.ele.tue.nl) provided
  225. Xuseful information on how to deal with the Apollo UNIX environment.
  226. X
  227. X    Wietse Venema (wietse@wzv.win.tue.nl),
  228. X    Mathematics and Computing Science,
  229. X    Eindhoven University of Technology,
  230. X    The Netherlands.
  231. END_OF_README
  232. if test 8553 -ne `wc -c <README`; then
  233.     echo shar: \"README\" unpacked with wrong size!
  234. fi
  235. # end of overwriting check
  236. fi
  237. if test -f miscd.c -a "${1}" != "-c" ; then 
  238.   echo shar: Will not over-write existing file \"miscd.c\"
  239. else
  240. echo shar: Extracting \"miscd.c\" \(1709 characters\)
  241. sed "s/^X//" >miscd.c <<'END_OF_miscd.c'
  242. X /*
  243. X  * Front end to the ULTRIX miscd service. The front end logs the remote host
  244. X  * name and then invokes the real miscd daemon. Install as "/usr/etc/miscd",
  245. X  * after moving the real miscd daemon to the "/usr/etc/..." directory.
  246. X  * Connections and diagnostics are logged through syslog(3).
  247. X  * 
  248. X  * The Ultrix miscd program implements the systat service, which pipes the
  249. X  * output from who(1) to stdout. This information is potentially useful to
  250. X  * systems crackers.
  251. X  * 
  252. X  * Compile with -DHOSTS_ACCESS in order to enable access control. See the
  253. X  * hosts_access(5) manual page for details.
  254. X  * 
  255. X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  256. X  */
  257. X
  258. X#ifndef lint
  259. Xstatic char sccsid[] = "@(#) miscd.c 1.1 91/01/06 22:30:32";
  260. X#endif
  261. X
  262. X#include <stdio.h>
  263. X#include <syslog.h>
  264. X
  265. X/* The following specifies where the vendor-provided daemon should go. */
  266. X
  267. X#define REAL_DAEMON    "/usr/etc/.../miscd"
  268. X
  269. Xmain(argc, argv)
  270. Xint     argc;
  271. Xchar  **argv;
  272. X{
  273. X    char   *fromhost();
  274. X    char   *host_name;
  275. X
  276. X    /*
  277. X     * Open a channel to the syslog daemon. Older versions of openlog()
  278. X     * require only two arguments.
  279. X     */
  280. X
  281. X#ifdef LOG_MAIL
  282. X    (void) openlog(argv[0], LOG_PID, LOG_MAIL);
  283. X#else
  284. X    (void) openlog(argv[0], LOG_PID);
  285. X#endif
  286. X
  287. X    /* Find out and report the remote host name. */
  288. X
  289. X    if ((host_name = fromhost()) == 0)
  290. X    host_name = "unknown";
  291. X    syslog(LOG_INFO, "connect from %s", host_name);
  292. X
  293. X    /* Check whether this host can access the service in argv[0]. */
  294. X
  295. X#ifdef HOSTS_ACCESS
  296. X    hosts_access(argv[0], host_name);
  297. X#endif
  298. X
  299. X    /* Invoke the real daemon program. */
  300. X
  301. X    (void) execv(REAL_DAEMON, argv);
  302. X    syslog(LOG_ERR, "%s: %m", REAL_DAEMON);
  303. X    return (1);
  304. X}
  305. END_OF_miscd.c
  306. if test 1709 -ne `wc -c <miscd.c`; then
  307.     echo shar: \"miscd.c\" unpacked with wrong size!
  308. fi
  309. # end of overwriting check
  310. fi
  311. if test -f tcpd.c -a "${1}" != "-c" ; then 
  312.   echo shar: Will not over-write existing file \"tcpd.c\"
  313. else
  314. echo shar: Extracting \"tcpd.c\" \(1873 characters\)
  315. sed "s/^X//" >tcpd.c <<'END_OF_tcpd.c'
  316. X /*
  317. X  * General front end for connection-oriented tcp/ip services. This program
  318. X  * logs the remote host name and then invokes the real daemon. For example,
  319. X  * install as /usr/etc/{fingerd,telnetd,ftpd,rlogind,rshd,rexecd}, after
  320. X  * saving the real daemons in the directory "/usr/etc/...". This arrangement
  321. X  * requires that the network daemons are started by inetd or something
  322. X  * similar. Connections and diagnostics are logged through syslog(3).
  323. X  * 
  324. X  * Compile with -DHOSTS_ACCESS in order to enable access control. See the
  325. X  * hosts_access(5) manual page for details.
  326. X  * 
  327. X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  328. X  */
  329. X
  330. X#ifndef lint
  331. Xstatic char sccsid[] = "@(#) tcpd.c 1.1 91/01/06 22:30:36";
  332. X#endif
  333. X
  334. X#include <stdio.h>
  335. X#include <syslog.h>
  336. X#include <sys/types.h>
  337. X#include <sys/param.h>
  338. X#ifndef MAXPATHNAMELEN
  339. X#define MAXPATHNAMELEN    BUFSIZ
  340. X#endif
  341. X
  342. X/* The following specifies where the vendor-provided daemons should go. */
  343. X
  344. X#define REAL_DAEMON_DIR    "/usr/etc/..."
  345. X
  346. Xmain(argc, argv)
  347. Xint     argc;
  348. Xchar  **argv;
  349. X{
  350. X    char   *fromhost();
  351. X    char   *host_name;
  352. X    char    path[MAXPATHNAMELEN];
  353. X
  354. X    /*
  355. X     * Open a channel to the syslog daemon. Older versions of openlog()
  356. X     * require only two arguments.
  357. X     */
  358. X
  359. X#ifdef LOG_MAIL
  360. X    (void) openlog(argv[0], LOG_PID, LOG_MAIL);
  361. X#else
  362. X    (void) openlog(argv[0], LOG_PID);
  363. X#endif
  364. X
  365. X    /* Find out and report the remote host name. */
  366. X
  367. X    if ((host_name = fromhost()) == 0)
  368. X    host_name = "unknown";
  369. X    syslog(LOG_INFO, "connect from %s", host_name);
  370. X
  371. X    /* Check whether this host can access the service in argv[0]. */
  372. X
  373. X#ifdef HOSTS_ACCESS
  374. X    hosts_access(argv[0], host_name);
  375. X#endif
  376. X
  377. X    /* Invoke the real daemon program. */
  378. X
  379. X    (void) sprintf(path, "%s/%s", REAL_DAEMON_DIR, argv[0]);
  380. X    (void) execv(path, argv);
  381. X    syslog(LOG_ERR, "%s: %m", path);
  382. X    return (1);
  383. X}
  384. END_OF_tcpd.c
  385. if test 1873 -ne `wc -c <tcpd.c`; then
  386.     echo shar: \"tcpd.c\" unpacked with wrong size!
  387. fi
  388. # end of overwriting check
  389. fi
  390. if test -f fromhost.c -a "${1}" != "-c" ; then 
  391.   echo shar: Will not over-write existing file \"fromhost.c\"
  392. else
  393. echo shar: Extracting \"fromhost.c\" \(3982 characters\)
  394. sed "s/^X//" >fromhost.c <<'END_OF_fromhost.c'
  395. X /*
  396. X  * fromhost() returns the name of the host at the other end of standard
  397. X  * input, the host address if name lookup fails, "stdin" if it is connected
  398. X  * to a terminal, or a null pointer in all other cases.
  399. X  * 
  400. X  * Protection against spoofing of naive rsh and rlogind implementations:
  401. X  * 
  402. X  * Initially, all we have is the remote host address. If the host address->name
  403. X  * mapping is available, fromhost() verifies that the host name->address
  404. X  * mapping yields the original host address. The idea is that it is much
  405. X  * easier to compromise some random address->name map (because there is one
  406. X  * for almost every network), than to compromise the name->address map that
  407. X  * is unique for your internet domain.
  408. X  * 
  409. X  * Anyway, if the test fails, fromhost() either drops the connection (when
  410. X  * compiled with -DPARANOID) or just returns the remote host address instead
  411. X  * of the bad remote host name (not compiled with -DPARANOID).
  412. X  * 
  413. X  * Diagnostics are reported through syslog(3).
  414. X  * 
  415. X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  416. X  */
  417. X
  418. X#ifndef lint
  419. Xstatic char sccsid[] = "@(#) fromhost.c 1.2 91/05/20 13:28:01";
  420. X#endif
  421. X
  422. X#include <stdio.h>
  423. X#include <sys/types.h>
  424. X#include <sys/param.h>
  425. X#include <sys/socket.h>
  426. X#include <syslog.h>
  427. X#include <netinet/in.h>
  428. X#include <netdb.h>
  429. X
  430. X#ifndef MAXHOSTNAMELEN
  431. X#define MAXHOSTNAMELEN    BUFSIZ
  432. X#endif
  433. X
  434. X/* The following are to be used in assignment context, not in comparisons */
  435. X
  436. X#define    GOOD    1
  437. X#define    BAD    0
  438. X
  439. X/* fromhost - find out what is at the other end of standard input */
  440. X
  441. Xchar   *fromhost()
  442. X{
  443. X    struct sockaddr sa;
  444. X    struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
  445. X    struct hostent *hp;
  446. X    int     sockt = fileno(stdin);
  447. X    int     length = sizeof(sa);
  448. X    static char remotehost[MAXHOSTNAMELEN + 1];
  449. X    char   *inet_ntoa();
  450. X    char   *strncpy();
  451. X
  452. X    /* Try to be smart if standard input is not connected to a socket. */
  453. X
  454. X    if (getpeername(sockt, &sa, &length) < 0) {
  455. X    if (isatty(sockt)) {
  456. X        return ("stdin");
  457. X    } else {
  458. X        syslog(LOG_ERR, "getpeername: %m");
  459. X        return (0);
  460. X    }
  461. X    }
  462. X    if (sa.sa_family != AF_INET) {
  463. X    syslog(LOG_ERR, "unknown address family %ld", (long) sa.sa_family);
  464. X    return (0);
  465. X    }
  466. X    /* Look up the remote host name. Use its address if name lookup fails. */
  467. X
  468. X    if ((hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
  469. X                sizeof(sin->sin_addr.s_addr),
  470. X                AF_INET)) == 0) {
  471. X    return (inet_ntoa(sin->sin_addr));
  472. X    }
  473. X    /* Save the host name before the gethostbyxxx() routines clobber it. */
  474. X
  475. X    (void) strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
  476. X    remotehost[sizeof(remotehost) - 1] = 0;
  477. X
  478. X    /*
  479. X     * Decide what to do if the host name does not match the address or if we
  480. X     * are unable to verify that the host name matches the address.
  481. X     */
  482. X
  483. X    if (matchname(remotehost, sin)) {
  484. X    return (remotehost);
  485. X    } else {
  486. X#ifdef    PARANOID
  487. X    exit(0);
  488. X#else
  489. X    return (inet_ntoa(sin->sin_addr));
  490. X#endif
  491. X    }
  492. X}
  493. X
  494. X/* matchname - determine if host name matches address */
  495. X
  496. Xstatic int matchname(remotehost, sin)
  497. Xchar   *remotehost;
  498. Xstruct sockaddr_in *sin;
  499. X{
  500. X    struct hostent *hp;
  501. X    int     i;
  502. X
  503. X    if ((hp = gethostbyname(remotehost)) == 0) {
  504. X
  505. X    /*
  506. X     * Unable to verify that the host name matches the address. This may be
  507. X     * a transient problem or a botched name server setup.
  508. X     */
  509. X
  510. X    syslog(LOG_ERR, "gethostbyname(%s): lookup failure", remotehost);
  511. X    return (BAD);
  512. X    } else {
  513. X
  514. X    /* Look up the host address in the address list we just got. */
  515. X
  516. X    for (i = 0; hp->h_addr_list[i]; i++) {
  517. X        if (memcmp(hp->h_addr_list[i], (caddr_t) & sin->sin_addr,
  518. X               sizeof(sin->sin_addr)) == 0)
  519. X        return (GOOD);
  520. X    }
  521. X
  522. X    /*
  523. X     * The host name does not map to the host address. Perhaps someone
  524. X     * has compromised a name server. More likely someone botched it, but
  525. X     * that could be dangerous, too.
  526. X     */
  527. X
  528. X    syslog(LOG_ERR, "host name/address mismatch: %s != %s",
  529. X           inet_ntoa(sin->sin_addr), hp->h_name);
  530. X    return (BAD);
  531. X    }
  532. X}
  533. END_OF_fromhost.c
  534. if test 3982 -ne `wc -c <fromhost.c`; then
  535.     echo shar: \"fromhost.c\" unpacked with wrong size!
  536. fi
  537. # end of overwriting check
  538. fi
  539. if test -f hosts_access.c -a "${1}" != "-c" ; then 
  540.   echo shar: Will not over-write existing file \"hosts_access.c\"
  541. else
  542. echo shar: Extracting \"hosts_access.c\" \(4992 characters\)
  543. sed "s/^X//" >hosts_access.c <<'END_OF_hosts_access.c'
  544. X#ifdef HOSTS_ACCESS
  545. X
  546. X /*
  547. X  * This module implements a simple but effective form of access control
  548. X  * based on host (or domain) names, netgroup, internet addresses (or network
  549. X  * numbers) and daemon process names, with wild card support.
  550. X  * 
  551. X  * Diagnostics are reported through syslog(3).
  552. X  * 
  553. X  * Compile with -DHOSTS_ACCESS in order to enable access control. See the
  554. X  * hosts_access(5) manual page for details.
  555. X  * 
  556. X  * Compile with -DNETGROUP if your library provides support for netgroups.
  557. X  * 
  558. X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  559. X  */
  560. X
  561. X#ifndef lint
  562. Xstatic char sccsid[] = "@(#) hosts_access.c 1.5 91/05/20 13:28:03";
  563. X#endif
  564. X
  565. X#include <stdio.h>
  566. X#include <syslog.h>
  567. X#include <ctype.h>
  568. X
  569. Xextern char *fgets();
  570. Xextern char *strchr();
  571. Xextern char *strtok();
  572. Xextern void exit();
  573. X
  574. X /* Path names of the access control files. */
  575. X
  576. X#define HOSTS_ALLOW    "/etc/hosts.allow"
  577. X#define HOSTS_DENY    "/etc/hosts.deny"
  578. X
  579. X /* Delimiters for lists of daemons or clients. */
  580. X
  581. Xstatic char sep[] = ", \t";
  582. X
  583. X /* Constants to be used in assignments only, not in comparisons... */
  584. X
  585. X#define    YES        1
  586. X#define    NO        0
  587. X
  588. X/* hosts_access - host access control facility */
  589. X
  590. Xhosts_access(daemon, client)
  591. Xchar   *daemon;
  592. Xchar   *client;
  593. X{
  594. X
  595. X    /*
  596. X     * If the (daemon, client) pair is matched by an entry in the file
  597. X     * /etc/hosts.allow, access is granted. Otherwise, if the (daemon,
  598. X     * client) pair is matched by an entry in /etc/hosts.deny, access is
  599. X     * denied. Otherwise, access is granted.
  600. X     * 
  601. X     * If a connection is refused, we write a syslog record, but do not notify
  602. X     * the client.
  603. X     */
  604. X
  605. X    if (table_match(HOSTS_ALLOW, daemon, client))
  606. X    return;
  607. X    if (table_match(HOSTS_DENY, daemon, client)) {
  608. X    syslog(LOG_WARNING, "refused connect from %s", client);
  609. X    exit(0);
  610. X    }
  611. X}
  612. X
  613. X/* table_match - match table entries with (daemon, client) pair */
  614. X
  615. Xint     table_match(table, daemon, client)
  616. Xchar   *table;
  617. Xchar   *daemon;
  618. Xchar   *client;
  619. X{
  620. X    FILE   *fp;
  621. X    char    sv_list[BUFSIZ];        /* becomes list of daemons */
  622. X    char   *cl_list;            /* becomes list of clients */
  623. X    int     match = NO;
  624. X    int     end;
  625. X
  626. X    /*
  627. X     * Process the table one line at a time. Lines that begin with a '#'
  628. X     * character are ignored. Non-comment lines are broken at the ':'
  629. X     * character (we complain if there is none). The left part is matched
  630. X     * against the daemon process name (argv[0]), the right part against the
  631. X     * host name. A non-existing table is treated as if it were an empty
  632. X     * table.
  633. X     */
  634. X
  635. X    if (fp = fopen(table, "r")) {
  636. X    while (!match && fgets(sv_list, sizeof(sv_list), fp)) {
  637. X        if (sv_list[end = strlen(sv_list) - 1] != '\n') {
  638. X        syslog(LOG_ERR, "%s: line exceeds STDIO buffer size", table);
  639. X        } else {
  640. X        sv_list[end] = '\0';        /* strip trailing newline */
  641. X        }
  642. X        if (sv_list[0] == '#') {        /* skip comments */
  643. X        continue;
  644. X        } else if ((cl_list = strchr(sv_list, ':')) == 0) {
  645. X        syslog(LOG_ERR, "%s: malformed entry: \"%s\"", table, sv_list);
  646. X        continue;
  647. X        } else {
  648. X        *cl_list++ = '\0';        /* break line at ":" */
  649. X        match = (list_match(sv_list, daemon)
  650. X             && list_match(cl_list, client));
  651. X        }
  652. X    }
  653. X    (void) fclose(fp);
  654. X    }
  655. X    return (match);
  656. X}
  657. X
  658. X/* list_match - match a string against a list of tokens */
  659. X
  660. Xint     list_match(list, string)
  661. Xchar   *list;
  662. Xchar   *string;
  663. X{
  664. X    char   *tok;
  665. X    int     tok_len;
  666. X    int     str_len;
  667. X
  668. X    /*
  669. X     * Process tokens one at a time. If a token has the magic value "ALL" the
  670. X     * match always succeeds. If the token is a domain name, return YES if it
  671. X     * matches the last fields of the string. If the token has the magic
  672. X     * value "LOCAL", return YES if the string does not contain a "."
  673. X     * character. If the token is a network number, return YES if it matches
  674. X     * the head of the string. If the token looks like a netgroup name,
  675. X     * return YES if the string is a (host) member of the netgroup.
  676. X     * Otherwise, return YES if the token fully matches the string. Note: we
  677. X     * assume that a daemon process name never begins or ends with a "." or
  678. X     * "@" character.
  679. X     */
  680. X
  681. X    for (tok = strtok(list, sep); tok; tok = strtok((char *) 0, sep)) {
  682. X    if (tok[0] == '.') {            /* domain: match last fields */
  683. X        if ((str_len = strlen(string)) > (tok_len = strlen(tok))
  684. X        && strcasecmp(tok, string + str_len - tok_len) == 0)
  685. X        return (YES);
  686. X#ifdef    NETGROUP
  687. X    } else if (tok[0] == '@') {        /* netgroup: look it up */
  688. X        if (innetgr(tok + 1, string, (char *) 0, (char *) 0))
  689. X        return (YES);
  690. X#endif
  691. X    } else if (strcasecmp(tok, "ALL") == 0) {    /* all: match any */
  692. X        return (YES);
  693. X    } else if (strcasecmp(tok, "LOCAL") == 0) {    /* local: no dots */
  694. X        if (strchr(string, '.') == 0)
  695. X        return (YES);
  696. X    } else if (!strcasecmp(tok, string)) {    /* match host name or address */
  697. X        return (YES);
  698. X    } else if (tok[(tok_len = strlen(tok)) - 1] == '.'    /* net number */
  699. X           && strncmp(tok, string, tok_len) == 0) {
  700. X        return (YES);
  701. X    }
  702. X    }
  703. X    return (NO);
  704. X}
  705. X
  706. X#endif
  707. END_OF_hosts_access.c
  708. if test 4992 -ne `wc -c <hosts_access.c`; then
  709.     echo shar: \"hosts_access.c\" unpacked with wrong size!
  710. fi
  711. # end of overwriting check
  712. fi
  713. if test -f Makefile -a "${1}" != "-c" ; then 
  714.   echo shar: Will not over-write existing file \"Makefile\"
  715. else
  716. echo shar: Extracting \"Makefile\" \(1484 characters\)
  717. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  718. X# @(#) Makefile 1.2 91/05/20 13:28:06
  719. X
  720. X## Begin configuration options
  721. X
  722. X# If you want to enable host access control, define the HOST_ACCESS macro
  723. X# in the  CFLAGS line. For example,
  724. X#
  725. X# CFLAGS = -O -DHOSTS_ACCESS 
  726. X#
  727. X# Note: host access control requires the strtok() and strchr() routines.
  728. X#
  729. X# If your library supports NIS-style netgroups, compile with -DNETGROUP
  730. X#
  731. X# If your C library does not have memcmp(3), compile with -Dmemcmp=bcmp.
  732. X#
  733. X# Compile with -DPARANOID if you want to refuse connections from hosts
  734. X# with names that do not match their address.
  735. X
  736. XCFLAGS    = -O -DHOSTS_ACCESS -DNETGROUP -DPARANOID
  737. X
  738. X# Include the file strcasecmp.o if it is not provided by your C library.
  739. X
  740. XAUX_OBJ    = # strcasecmp.o
  741. X
  742. X# Some System-V versions require that you explicitly specify the networking
  743. X# libraries.
  744. X
  745. XLIBS    =
  746. X
  747. X## End configuration options
  748. X
  749. XTCPD_OBJ= tcpd.o fromhost.o hosts_access.o
  750. XMISC_OBJ= miscd.o fromhost.o hosts_access.o
  751. X
  752. Xall:    tcpd miscd
  753. X
  754. Xtcpd:    $(TCPD_OBJ) $(AUX_OBJ)
  755. X    $(CC) $(CFLAGS) -o $@ $(TCPD_OBJ) $(AUX_OBJ) $(LIBS)
  756. X
  757. Xmiscd:    $(MISC_OBJ) $(AUX_OBJ)
  758. X    $(CC) $(CFLAGS) -o $@ $(MISC_OBJ) $(AUX_OBJ) $(LIBS)
  759. X
  760. Xshar:    
  761. X    @shar README miscd.c tcpd.c fromhost.c hosts_access.c Makefile \
  762. X    hosts_access.5 strcasecmp.c BLURB
  763. X
  764. Xarchive:
  765. X    $(ARCHIVE) README miscd.c tcpd.c fromhost.c hosts_access.c Makefile \
  766. X    hosts_access.5 strcasecmp.c BLURB
  767. X
  768. Xclean:
  769. X    rm -f tcpd miscd *.o core
  770. X
  771. Xlint:
  772. X    lint -DHOSTS_ACCESS tcpd.c fromhost.c hosts_access.c
  773. X    lint -DHOSTS_ACCESS miscd.c fromhost.c hosts_access.c
  774. END_OF_Makefile
  775. if test 1484 -ne `wc -c <Makefile`; then
  776.     echo shar: \"Makefile\" unpacked with wrong size!
  777. fi
  778. # end of overwriting check
  779. fi
  780. if test -f hosts_access.5 -a "${1}" != "-c" ; then 
  781.   echo shar: Will not over-write existing file \"hosts_access.5\"
  782. else
  783. echo shar: Extracting \"hosts_access.5\" \(3901 characters\)
  784. sed "s/^X//" >hosts_access.5 <<'END_OF_hosts_access.5'
  785. X.TH HOSTS_ACCESS 5
  786. X.ad
  787. X.fi
  788. X.SH NAME
  789. Xhosts_access \- host access control files
  790. X.SH DESCRIPTION
  791. X.ad
  792. X.fi
  793. XThis manual page describes a simple, but effective, access control
  794. Xfacility that is based on host (or domain) names, netgroups, internet
  795. Xaddresses (or network numbers) and on network daemon process names.
  796. X.PP
  797. XIn the following text, \fIdaemon\fP is the the process name (argv[0]
  798. Xvalue) of a network daemon process, and \fIclient\fP is the name or
  799. Xinternet address of a host.
  800. X.IP o
  801. XAccess will be granted if a (daemon,client) pair is matched by an
  802. Xentry in the \fI/etc/hosts.allow\fP file.
  803. X.IP o
  804. XIf the previous test fails (perhaps because the \fIhosts.allow\fP file
  805. Xdoes not exist), access will be denied if a (daemon,client) pair is
  806. Xmatched by an entry in the \fI/etc/hosts.deny\fP file.
  807. X.IP o
  808. XIf the previous test fails (perhaps because the \fIhosts.deny\fP file
  809. Xdoes not exist), access will be granted.
  810. X.PP
  811. XA non-existing access control file is treated as if it were an empty
  812. Xfile. Thus, access control can be turned off by providing no access
  813. Xcontrol files.
  814. X.PP
  815. XThe format of the access control files is as follows.
  816. X.IP o
  817. XLines that begin with a `#' character are ignored.
  818. X.IP o
  819. XOther lines should have the format:
  820. X.sp
  821. X.ti +5
  822. Xdaemon_list : client_list
  823. X.LP
  824. X\fIdaemon_list\fP is a list of one or more daemon process names
  825. X(argv[0] values); \fIclient_list\fP is a list of one or more host
  826. Xnames, domain names, netgroups, internet addresses or internet network
  827. Xnumbers.  List elements should be separated by blanks or commas.  With
  828. Xthe exception of netgroup lookups, all access control code is case
  829. Xinsensitive.
  830. X.PP
  831. XClient_list fields that specify a \fIdomain name\fP should begin with a
  832. X`.' character (see example below). Internet \fInetwork numbers\fP (as
  833. Xopposed to internet \fIhost numbers\fP) should be terminated with a `.'
  834. Xcharacter. A \fInetgroup\fP name should begin with the `@' character.
  835. XNetgroups are usually supported on systems with NIS (formerly YP)
  836. Xdata bases.
  837. X.PP
  838. XSpecial meaning is given to the magic token \fIALL\fP.  If it appears
  839. Xin the \fIdaemon_list\fP part of a line, this token matches all network
  840. Xdaemon process names.  If the magic token appears in the
  841. X\fIclient_list\fP part of a line, it matches all clients.
  842. X.PP
  843. XAnother token that receives special treatment is \fILOCAL\fP. It
  844. Xmatches any string that does not contain a dot character.
  845. X.SH EXAMPLES
  846. XThe following example restricts all services to hosts within the local
  847. Xdomain (no `.' character in the host name), \fIhost.dom.ain\fP, and all
  848. Xhosts below the \fI.some.domain\fP:
  849. X.PP
  850. X/etc/hosts.allow:
  851. X.in +5
  852. XALL: LOCAL, host.dom.ain, .some.domain
  853. X.PP
  854. X/etc/hosts.deny:
  855. X.in +5
  856. XALL: ALL
  857. X.PP
  858. XA similar example, but using netgroup names:
  859. X.PP
  860. X/etc/hosts.allow:
  861. X.in +5
  862. XALL: @netgroupname
  863. X.PP
  864. X/etc/hosts.deny:
  865. X.in +5
  866. XALL: ALL
  867. X.PP
  868. XIn order to deny some hosts all services, except ftp:
  869. X.PP
  870. X/etc/hosts.allow:
  871. X.in +5
  872. Xin.ftpd: ALL
  873. X.PP
  874. X/etc/hosts.deny
  875. X.in +5
  876. XALL: some.host.name, .some.domain
  877. X.SH DIAGNOSTICS
  878. X.ad
  879. X.fi
  880. XA syslog record is produced when a connection is refused; when a syntax
  881. Xerror is found in a host access control file; when the length of a line
  882. Xin a host access control file exceeds the stdio(3) buffer size.
  883. X.SH FILES
  884. X.na
  885. X.nf
  886. X/etc/hosts.allow, (daemon,client) pairs that are granted access.
  887. X/etc/hosts.deny, (daemon,client) pairs that are denied access.
  888. X.SH BUGS
  889. X.ad
  890. X.fi
  891. XIf there are problems with a name server, the access control software
  892. Xwill use a host\'s address instead of its name.  A workaround is to
  893. Xalso list internet addresses and network numbers in the access-control
  894. Xfiles.
  895. X.PP
  896. XDomain name server lookups are case insensitive; NIS (formerly YP)
  897. Xnetgroup lookups are case sensitive.
  898. X.SH AUTHOR
  899. X.na
  900. X.nf
  901. XWietse Venema
  902. XEindhoven University of Technology
  903. XDepartment of Mathematics and Computer Science
  904. XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  905. X\" @(#) hosts_access.5 1.7 91/05/20 13:28:08
  906. END_OF_hosts_access.5
  907. if test 3901 -ne `wc -c <hosts_access.5`; then
  908.     echo shar: \"hosts_access.5\" unpacked with wrong size!
  909. fi
  910. # end of overwriting check
  911. fi
  912. if test -f strcasecmp.c -a "${1}" != "-c" ; then 
  913.   echo shar: Will not over-write existing file \"strcasecmp.c\"
  914. else
  915. echo shar: Extracting \"strcasecmp.c\" \(3767 characters\)
  916. sed "s/^X//" >strcasecmp.c <<'END_OF_strcasecmp.c'
  917. X/*
  918. X * Copyright (c) 1987 Regents of the University of California.
  919. X * All rights reserved.
  920. X *
  921. X * Redistribution and use in source and binary forms are permitted
  922. X * provided that the above copyright notice and this paragraph are
  923. X * duplicated in all such forms and that any documentation,
  924. X * advertising materials, and other materials related to such
  925. X * distribution and use acknowledge that the software was developed
  926. X * by the University of California, Berkeley.  The name of the
  927. X * University may not be used to endorse or promote products derived
  928. X * from this software without specific prior written permission.
  929. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  930. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  931. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  932. X */
  933. X
  934. X#if defined(LIBC_SCCS) && !defined(lint)
  935. Xstatic char sccsid[] = "@(#)strcasecmp.c    5.6 (Berkeley) 6/27/88";
  936. X#endif /* LIBC_SCCS and not lint */
  937. X
  938. X#include <sys/types.h>
  939. X
  940. X/*
  941. X * This array is designed for mapping upper and lower case letter
  942. X * together for a case independent comparison.  The mappings are
  943. X * based upon ascii character sequences.
  944. X */
  945. Xstatic u_char charmap[] = {
  946. X    '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  947. X    '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  948. X    '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  949. X    '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  950. X    '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  951. X    '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  952. X    '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  953. X    '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  954. X    '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  955. X    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  956. X    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  957. X    '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  958. X    '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  959. X    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  960. X    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  961. X    '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  962. X    '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  963. X    '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  964. X    '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  965. X    '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  966. X    '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  967. X    '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  968. X    '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  969. X    '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  970. X    '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  971. X    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  972. X    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  973. X    '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
  974. X    '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  975. X    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  976. X    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  977. X    '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  978. X};
  979. X
  980. Xstrcasecmp(s1, s2)
  981. X    char *s1, *s2;
  982. X{
  983. X    register u_char    *cm = charmap,
  984. X            *us1 = (u_char *)s1,
  985. X            *us2 = (u_char *)s2;
  986. X
  987. X    while (cm[*us1] == cm[*us2++])
  988. X        if (*us1++ == '\0')
  989. X            return(0);
  990. X    return(cm[*us1] - cm[*--us2]);
  991. X}
  992. X
  993. Xstrncasecmp(s1, s2, n)
  994. X    char *s1, *s2;
  995. X    register int n;
  996. X{
  997. X    register u_char    *cm = charmap,
  998. X            *us1 = (u_char *)s1,
  999. X            *us2 = (u_char *)s2;
  1000. X
  1001. X    while (--n >= 0 && cm[*us1] == cm[*us2++])
  1002. X        if (*us1++ == '\0')
  1003. X            return(0);
  1004. X    return(n < 0 ? 0 : cm[*us1] - cm[*--us2]);
  1005. X}
  1006. END_OF_strcasecmp.c
  1007. if test 3767 -ne `wc -c <strcasecmp.c`; then
  1008.     echo shar: \"strcasecmp.c\" unpacked with wrong size!
  1009. fi
  1010. # end of overwriting check
  1011. fi
  1012. if test -f BLURB -a "${1}" != "-c" ; then 
  1013.   echo shar: Will not over-write existing file \"BLURB\"
  1014. else
  1015. echo shar: Extracting \"BLURB\" \(1412 characters\)
  1016. sed "s/^X//" >BLURB <<'END_OF_BLURB'
  1017. X@(#) BLURB 1.3 91/05/20 13:28:10
  1018. X
  1019. XThis package provides a couple of tiny programs that log all requests
  1020. Xto connection-oriented tcp/ip services (examples: FINGER, SYSTAT, FTP,
  1021. XTELNET, RLOGIN, RSH, EXEC), with optional access control on the basis
  1022. Xof host (or domain) names, internet addresses (or network numbers) and
  1023. Xdaemon process names.
  1024. X
  1025. XThe programs are nothing but small front ends. By default, they just
  1026. Xlog the remote host name and then invoke the real daemon. The programs
  1027. Xshould not require any changes to existing software or configuration
  1028. Xfiles.
  1029. X
  1030. XConnections are reported through the syslog(3) facility. Each record
  1031. Xcontains a time stamp, the remote host name and the name of the service
  1032. Xrequested. Such information can be useful to detect break-in attempts
  1033. Xor other undesirable activities, especially when logfile information
  1034. Xfrom several hosts is merged.
  1035. X
  1036. XThe optional access-control facility may be useful when, for whatever
  1037. Xreason, it is not possible to handle access control at a more suitable
  1038. Xlevel (such as an internet router).
  1039. X
  1040. XEnhancements over the previous release are: protection against rlogin
  1041. Xand rsh attacks through compromised domain name servers, optional
  1042. Xnetgroup support for systems with NIS (formerly YP), and an extension
  1043. Xof the wild card patterns supported by the access control files.
  1044. X
  1045. X    Wietse Venema (wietse@wzv.win.tue.nl),
  1046. X    Eindhoven University of Technology,
  1047. X    The Netherlands.
  1048. END_OF_BLURB
  1049. if test 1412 -ne `wc -c <BLURB`; then
  1050.     echo shar: \"BLURB\" unpacked with wrong size!
  1051. fi
  1052. # end of overwriting check
  1053. fi
  1054. echo shar: End of shell archive.
  1055. exit 0
  1056.  
  1057. exit 0 # Just in case...
  1058. -- 
  1059. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1060. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1061. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1062. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1063.